<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>007实现Modal | Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="前言日志，各位看官就当乐子看吧。 正经人谁写日记啊？！！    ——鹅城县长 不用想乱七八糟的，写就完事儿了。 Vue3实现 Modal不用看我的文章了（感觉我只能背这段代码了），直接看原文去理解吧，链接：https:&#x2F;&#x2F;segmentfault.com&#x2F;a&#x2F;1190000038928664 实现一个Modal模态对话框，首先分析一下结构和能够预想到的内容，需要的结构：  遮罩层 标题 主体内容">
<meta property="og:type" content="article">
<meta property="og:title" content="007实现Modal">
<meta property="og:url" content="http://example.com/2023/03/22/007%E5%AE%9E%E7%8E%B0Modal/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="前言日志，各位看官就当乐子看吧。 正经人谁写日记啊？！！    ——鹅城县长 不用想乱七八糟的，写就完事儿了。 Vue3实现 Modal不用看我的文章了（感觉我只能背这段代码了），直接看原文去理解吧，链接：https:&#x2F;&#x2F;segmentfault.com&#x2F;a&#x2F;1190000038928664 实现一个Modal模态对话框，首先分析一下结构和能够预想到的内容，需要的结构：  遮罩层 标题 主体内容">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2023-03-22T13:42:24.782Z">
<meta property="article:modified_time" content="2023-03-22T14:12:43.609Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 6.3.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-007实现Modal" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2023/03/22/007%E5%AE%9E%E7%8E%B0Modal/" class="article-date">
  <time class="dt-published" datetime="2023-03-22T13:42:24.782Z" itemprop="datePublished">2023-03-22</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="p-name article-title" itemprop="headline name">
      007实现Modal
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>日志，各位看官就当乐子看吧。</p>
<p><strong>正经人谁写日记啊？！！</strong>    ——鹅城县长</p>
<p>不用想乱七八糟的，写就完事儿了。</p>
<h1 id="Vue3"><a href="#Vue3" class="headerlink" title="Vue3"></a>Vue3</h1><h2 id="实现-Modal"><a href="#实现-Modal" class="headerlink" title="实现 Modal"></a>实现 Modal</h2><p>不用看我的文章了（感觉我只能背这段代码了），直接看原文去理解吧，链接：<a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000038928664">https://segmentfault.com/a/1190000038928664</a></p>
<p>实现一个<code>Modal</code>模态对话框，首先分析一下结构和能够预想到的内容，需要的结构：</p>
<ul>
<li>遮罩层</li>
<li>标题</li>
<li>主体内容</li>
<li>按钮</li>
</ul>
<p>主体部分可能是一段文字，也可能是段<code>HTML</code>代码。好了，下面具体实现。</p>
<h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><p><code>Modal</code>会被<code>app.use(Modal)</code>作为一个插件调用，所以放在<code>plugin</code>文件夹中。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">├── plugins</span><br><span class="line">│   └── modal</span><br><span class="line">│       ├── Content.tsx // 维护 Modal 的内容，用于 h 函数和 jsx 语法</span><br><span class="line">│       ├── Modal.vue // 基础组件</span><br><span class="line">│       ├── config.ts // 全局默认配置</span><br><span class="line">│       ├── index.ts // 入口</span><br><span class="line">│       ├── locale // 国际化相关</span><br><span class="line">│       │   ├── index.ts</span><br><span class="line">│       │   └── lang</span><br><span class="line">│       │       ├── en-US.ts</span><br><span class="line">│       │       ├── zh-CN.ts</span><br><span class="line">│       │       └── zh-TW.ts</span><br><span class="line">│       └── modal.type.ts // ts类型声明相关</span><br></pre></td></tr></table></figure>

<h3 id="组件代码"><a href="#组件代码" class="headerlink" title="组件代码"></a>组件代码</h3><p>对话框通常存在于vue实例之外，挂载在<code>body</code>上。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">// Modal.vue</span><br><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Teleport</span> <span class="attr">to</span>=<span class="string">&quot;body&quot;</span> <span class="attr">:disabled</span>=<span class="string">&quot;!isTeleport&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">v-if</span>=<span class="string">&quot;modelValue&quot;</span> <span class="attr">class</span>=<span class="string">&quot;modal&quot;</span>&gt;</span></span><br><span class="line">            <span class="comment">&lt;!-- 遮罩层 --&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span></span></span><br><span class="line"><span class="tag">                <span class="attr">class</span>=<span class="string">&quot;mask&quot;</span></span></span><br><span class="line"><span class="tag">                <span class="attr">:style</span>=<span class="string">&quot;style&quot;</span></span></span><br><span class="line"><span class="tag">                @<span class="attr">click</span>=<span class="string">&quot;maskClose &amp;&amp; !loading &amp;&amp; handleCancel()&quot;</span></span></span><br><span class="line"><span class="tag">                &gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;modal__main&quot;</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 标题区域 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;modal__title line line--b&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>&#123;&#123; title || t(&quot;r.title&quot;) &#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">span</span></span></span><br><span class="line"><span class="tag">                        <span class="attr">v-if</span>=<span class="string">&quot;close&quot;</span></span></span><br><span class="line"><span class="tag">                        <span class="attr">:title</span>=<span class="string">&quot;t(&#x27;r.close&#x27;)&quot;</span></span></span><br><span class="line"><span class="tag">                        <span class="attr">class</span>=<span class="string">&quot;close&quot;</span></span></span><br><span class="line"><span class="tag">                        @<span class="attr">click</span>=<span class="string">&quot;!loading &amp;&amp; handleCancel()&quot;</span></span></span><br><span class="line"><span class="tag">                        &gt;</span>✕&lt;/span</span><br><span class="line">                        &gt;</span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 主体内容区域 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;modal__content&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">Content</span> <span class="attr">v-if</span>=<span class="string">&quot;typeof content === &#x27;function&#x27;&quot;</span> <span class="attr">:render</span>=<span class="string">&quot;content&quot;</span> /&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">slot</span> <span class="attr">v-else</span>&gt;</span></span><br><span class="line">                        &#123;&#123; content &#125;&#125;</span><br><span class="line">                    <span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 按钮 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;modal__btns line line--t&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">button</span> <span class="attr">:disabled</span>=<span class="string">&quot;loading&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;handleConfirm&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;loading&quot;</span> <span class="attr">v-if</span>=<span class="string">&quot;loading&quot;</span>&gt;</span> ❍ <span class="tag">&lt;/<span class="name">span</span>&gt;</span>&#123;&#123; t(&quot;r.confirm&quot;) &#125;&#125;</span><br><span class="line">                    <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;!loading &amp;&amp; handleCancel()&quot;</span>&gt;</span></span><br><span class="line">                        &#123;&#123; t(&quot;r.cancel&quot;) &#125;&#125;</span><br><span class="line">                    <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">Teleport</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>使用<code>teleport</code>将内容传送到<code>body</code>标签下。关注主体内容代码，</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;modal__content&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Content</span> <span class="attr">v-if</span>=<span class="string">&quot;typeof content === &#x27;function&#x27;&quot;</span> <span class="attr">:render</span>=<span class="string">&quot;content&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">slot</span> <span class="attr">v-else</span>&gt;</span></span><br><span class="line">        &#123;&#123; content &#125;&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>其中<code>Content</code>组件是为了兼容<code>Modal</code>以API形式调用的方式。<code>Content</code>：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Content.tsx</span></span><br><span class="line"><span class="keyword">import</span> &#123; h &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Content</span> = (<span class="params">props: &#123; render: (h: any) =&gt; <span class="keyword">void</span> &#125;</span>) =&gt; props.<span class="title function_">render</span>(h);</span><br><span class="line"><span class="title class_">Content</span>.<span class="property">props</span> = [<span class="string">&#x27;render&#x27;</span>];</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">Content</span>;</span><br></pre></td></tr></table></figure>
<p>当基于API调用<code>Modal</code>，如，</p>
<ul>
<li>h 渲染函数<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//  h 渲染函数</span></span><br><span class="line">$modal.<span class="title function_">show</span>(&#123;</span><br><span class="line">    <span class="attr">title</span>: <span class="string">&#x27;演示 h 函数&#x27;</span>,</span><br><span class="line">    <span class="title function_">content</span>(<span class="params">h</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">h</span>(</span><br><span class="line">            <span class="string">&#x27;div&#x27;</span>,</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="attr">style</span>: <span class="string">&#x27;color:red;&#x27;</span>,</span><br><span class="line">                <span class="attr">onClick</span>: <span class="function">(<span class="params">$event</span>)=&gt;</span>&#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;click&#x27;</span>, $event.<span class="property">target</span>)&#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">&#x27;hello world&#x27;</span></span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li>
<li>JSX 语法<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// JSX（javascript的扩展，标记语言和js可以一起写）</span></span><br><span class="line">$modal.<span class="title function_">show</span>(&#123;</span><br><span class="line">  <span class="attr">title</span>: <span class="string">&#x27;演示 jsx 语法&#x27;</span>,</span><br><span class="line">  <span class="title function_">content</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">onClick</span>=<span class="string">&#123;($event:</span> <span class="attr">Event</span>) =&gt;</span> console.log(&#x27;clicked&#x27;, $event.target)&#125;</span></span><br><span class="line"><span class="language-xml">      &gt;</span></span><br><span class="line"><span class="language-xml">        hello world ~</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
另一种方式（v-else分支内），对主体内容的填写通过默认插槽或者prop</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Modal</span> <span class="attr">v-model</span>=<span class="string">&#x27;show&#x27;</span> <span class="attr">title</span>=<span class="string">&#x27;默认插槽&#x27;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span>hello world<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">Modal</span>&gt;</span></span><br><span class="line">// content 属性</span><br><span class="line"><span class="tag">&lt;<span class="name">Modal</span> <span class="attr">v-model</span>=<span class="string">&quot;show&quot;</span> <span class="attr">title</span>=<span class="string">&quot;演示 content&quot;</span> <span class="attr">content</span>=<span class="string">&quot;hello world~&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>

<p>如上，支持通过<code>4种方式</code>使用<code>Modal</code>组件。</p>
<h3 id="组价API化"><a href="#组价API化" class="headerlink" title="组价API化"></a>组价API化</h3><p><code>Vue3</code>中实现组件API化，可以这么写，</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Modal</span> <span class="keyword">from</span> <span class="string">&#x27;./Modal.vue&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> container = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;div&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> vnode = <span class="title function_">createVNode</span>(<span class="title class_">Modal</span>);</span><br><span class="line"><span class="title function_">render</span>(vnode, container);</span><br><span class="line"><span class="keyword">const</span> instance = vnode.<span class="property">component</span>;</span><br><span class="line"><span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(container);</span><br></pre></td></tr></table></figure>
<p>将组件转化成虚拟<code>dom</code>，再通过渲染函数渲染到div上，最后动态添加到body中。<br>看具体代码，</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// index.ts</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">App</span>, createVNode, render &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Modal</span> <span class="keyword">from</span> <span class="string">&#x27;./Modal.vue&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> config <span class="keyword">from</span> <span class="string">&#x27;./config&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 新增 Modal 的 install 方法，为了可以被 `app.use(Modal)`（Vue使用插件的的规则）</span></span><br><span class="line"><span class="title class_">Modal</span>.<span class="property">install</span> = <span class="function">(<span class="params">app: App, options</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 可覆盖默认的全局配置</span></span><br><span class="line">  <span class="title class_">Object</span>.<span class="title function_">assign</span>(config.<span class="property">props</span>, options.<span class="property">props</span> || &#123;&#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 注册全局组件 Modal</span></span><br><span class="line">  app.<span class="title function_">component</span>(<span class="title class_">Modal</span>.<span class="property">name</span>, <span class="title class_">Modal</span>);</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 注册全局 API</span></span><br><span class="line">  app.<span class="property">config</span>.<span class="property">globalProperties</span>.<span class="property">$modal</span> = &#123;</span><br><span class="line">    <span class="title function_">show</span>(<span class="params">&#123;</span></span><br><span class="line"><span class="params">      title = <span class="string">&#x27;&#x27;</span>,</span></span><br><span class="line"><span class="params">      content = <span class="string">&#x27;&#x27;</span>,</span></span><br><span class="line"><span class="params">      close = config.props!.close</span></span><br><span class="line"><span class="params">    &#125;</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> container = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;div&#x27;</span>);</span><br><span class="line">      <span class="keyword">const</span> vnode = <span class="title function_">createVNode</span>(<span class="title class_">Modal</span>);</span><br><span class="line">      <span class="title function_">render</span>(vnode, container);</span><br><span class="line">      <span class="keyword">const</span> instance = vnode.<span class="property">component</span>;</span><br><span class="line">      <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(container);</span><br><span class="line">        </span><br><span class="line">      <span class="comment">// 获取实例的 props ，进行传递 props</span></span><br><span class="line">      <span class="keyword">const</span> &#123; props &#125; = instance;</span><br><span class="line"></span><br><span class="line">      <span class="title class_">Object</span>.<span class="title function_">assign</span>(props, &#123;</span><br><span class="line">        <span class="attr">isTeleport</span>: <span class="literal">false</span>,</span><br><span class="line">        <span class="comment">// 在父组件上我们用 v-model 来控制显示，语法糖对应的 prop 为 modelValue</span></span><br><span class="line">        <span class="attr">modelValue</span>: <span class="literal">true</span>,</span><br><span class="line">        title,</span><br><span class="line">        content,</span><br><span class="line">        close</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">Modal</span>;</span><br></pre></td></tr></table></figure>

<h3 id="如何监听事件"><a href="#如何监听事件" class="headerlink" title="如何监听事件"></a>如何监听事件</h3><p>在Modal中已经写好的事件：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Modal.vue</span></span><br><span class="line"><span class="title function_">setup</span>(<span class="params">props, ctx</span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> instance = <span class="title function_">getCurrentInstance</span>();</span><br><span class="line">  <span class="title function_">onBeforeMount</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    instance.<span class="property">_hub</span> = &#123;</span><br><span class="line">      <span class="string">&#x27;on-cancel&#x27;</span>: <span class="function">() =&gt;</span> &#123;&#125;,</span><br><span class="line">      <span class="string">&#x27;on-confirm&#x27;</span>: <span class="function">() =&gt;</span> &#123;&#125;</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">handleConfirm</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    ctx.<span class="title function_">emit</span>(<span class="string">&#x27;on-confirm&#x27;</span>);</span><br><span class="line">    instance.<span class="property">_hub</span>[<span class="string">&#x27;on-confirm&#x27;</span>]();</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">handleCancel</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    ctx.<span class="title function_">emit</span>(<span class="string">&#x27;on-cancel&#x27;</span>);</span><br><span class="line">    ctx.<span class="title function_">emit</span>(<span class="string">&#x27;update:modelValue&#x27;</span>, <span class="literal">false</span>);</span><br><span class="line">    instance.<span class="property">_hub</span>[<span class="string">&#x27;on-cancel&#x27;</span>]();</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    handleConfirm,</span><br><span class="line">    handleCancel</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们可以看到在 上面的 setup 方法内部，获取了当前组件的实例，在组件挂载前，我们擅自添加了一个属性 _hub（且叫它事件处理中心吧~），并且添加了两个空语句方法 on-cancel，on-confirm，且在点击事件里都有被对应的调用到了。<br>再看看确认事件的具体实现，这里实现了点击确定，如果确定事件是一个异步操作，那我们需要在确定按钮上显示 loading 图标，且禁用按钮，来等待异步完成。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// index.ts</span></span><br><span class="line">app.<span class="property">config</span>.<span class="property">globalProperties</span>.<span class="property">$modal</span> = &#123;</span><br><span class="line">  <span class="title function_">show</span>(<span class="params">&#123;</span></span><br><span class="line"><span class="params">    /* 其他选项 */</span></span><br><span class="line"><span class="params">    onConfirm,</span></span><br><span class="line"><span class="params">    onCancel</span></span><br><span class="line"><span class="params">  &#125;</span>) &#123;</span><br><span class="line">    <span class="comment">/* ... */</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> &#123; props, _hub &#125; = instance;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">_closeModal</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">      props.<span class="property">modelValue</span> = <span class="literal">false</span>;</span><br><span class="line">      container.<span class="property">parentNode</span>!.<span class="title function_">removeChild</span>(container);</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="comment">// 往 _hub 新增事件的具体实现</span></span><br><span class="line">    <span class="title class_">Object</span>.<span class="title function_">assign</span>(_hub, &#123;</span><br><span class="line">      <span class="keyword">async</span> <span class="string">&#x27;on-confirm&#x27;</span>() &#123;</span><br><span class="line">        <span class="keyword">if</span> (onConfirm) &#123;</span><br><span class="line">          <span class="keyword">const</span> fn = <span class="title function_">onConfirm</span>();</span><br><span class="line">          <span class="comment">// 当方法返回为 Promise</span></span><br><span class="line">          <span class="keyword">if</span> (fn &amp;&amp; fn.<span class="property">then</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">              props.<span class="property">loading</span> = <span class="literal">true</span>;</span><br><span class="line">              <span class="keyword">await</span> fn;</span><br><span class="line">              props.<span class="property">loading</span> = <span class="literal">false</span>;</span><br><span class="line">              <span class="title function_">_closeModal</span>();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">              <span class="comment">// 发生错误时，不关闭弹框</span></span><br><span class="line">              <span class="variable language_">console</span>.<span class="title function_">error</span>(err);</span><br><span class="line">              props.<span class="property">loading</span> = <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="title function_">_closeModal</span>();</span><br><span class="line">          &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="title function_">_closeModal</span>();</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="string">&#x27;on-cancel&#x27;</span>() &#123;</span><br><span class="line">        onCancel &amp;&amp; <span class="title function_">onCancel</span>();</span><br><span class="line">        <span class="title function_">_closeModal</span>();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ... */</span></span><br><span class="line"></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>其他内容请看原文，如国际化、与ts的结合。</p>
<h1 id="彩蛋"><a href="#彩蛋" class="headerlink" title="彩蛋"></a>彩蛋</h1><p>今天没有彩蛋，还好没停更。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2023/03/22/007%E5%AE%9E%E7%8E%B0Modal/" data-id="clfjqowu90006ewaa81ce6eyj" data-title="007实现Modal" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2023/03/22/008ES6/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          008ES6
        
      </div>
    </a>
  
  
    <a href="/2023/03/22/006%E5%A4%A7%E5%AE%9E%E8%AF%9D/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">006大实话</div>
    </a>
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%99%BE%E6%97%A5%E5%8D%9A%E5%AE%A2%E8%AE%A1%E5%88%92/">百日博客计划</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/ES6/" rel="tag">ES6</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/hexo/" rel="tag">hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/uniapp/" rel="tag">uniapp</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%89%8D%E7%AB%AF/" rel="tag">前端</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/ES6/" style="font-size: 10px;">ES6</a> <a href="/tags/hexo/" style="font-size: 10px;">hexo</a> <a href="/tags/uniapp/" style="font-size: 10px;">uniapp</a> <a href="/tags/%E5%89%8D%E7%AB%AF/" style="font-size: 10px;">前端</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2023/03/">March 2023</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2023/03/24/025uniapp-done/">025uniapp-done</a>
          </li>
        
          <li>
            <a href="/2023/03/23/024uniapp%E7%AC%AC%E4%B8%89%E5%A4%A9/">024uniapp第三天</a>
          </li>
        
          <li>
            <a href="/2023/03/22/023gitee-hexo%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/">023gitee+hexo搭建个人博客</a>
          </li>
        
          <li>
            <a href="/2023/03/22/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8MDN%E6%96%87%E6%A1%A3/">(no title)</a>
          </li>
        
          <li>
            <a href="/2023/03/22/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2023 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/js/jquery-3.4.1.min.js"></script>



  
<script src="/fancybox/jquery.fancybox.min.js"></script>




<script src="/js/script.js"></script>





  </div>
</body>
</html>